package lysjmaster.base.auth.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import lombok.extern.slf4j.Slf4j;
import lysjmaster.base.auth.domain.Permission;
import lysjmaster.base.auth.domain.RolePermission;
import lysjmaster.base.auth.domain.User;
import lysjmaster.base.auth.repository.PermissionRepository;
import lysjmaster.base.auth.repository.RolePermissionRepository;
import lysjmaster.base.auth.repository.UserRepository;
import lysjmaster.base.auth.vo.PermissionVO;
import lysjmaster.base.common.exception.BaseException;
import lysjmaster.base.common.spring.base.BaseRepository;
import lysjmaster.base.common.spring.base.BaseService;
import lysjmaster.base.common.validation.Validation;
import lysjmaster.base.common.validation.domain.BindingResult;
import lysjmaster.base.common.web.ParamUtil;
import lysjmaster.base.common.web.Resp;
import lysjmaster.base.common.web.RespUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Created by zk on 2019-12-05 2:23
 * @description
 */
@Slf4j
@Service
@Transactional
public class PermissionService implements BaseService<Permission> {
    @Resource
    private PermissionRepository permissionRepository;
    @Resource
    private RolePermissionRepository rolePermissionRepository;
    @Resource
    private UserRepository userRepository;
    @Resource
    private AdminAuthentication adminAuthentication;

    @Override
    public BaseRepository<Permission> getRepository() {
        return permissionRepository;
    }

    @Transactional
    public void deletePermission(String[] ids) {
        List<Permission> list = findAll(ids);
        boolean deleteLevelThree = false;
        for (Permission permission : list) {
            if (permission.getLevel() == 3) {
                deleteLevelThree = true;
                break;
            }
        }
        delete(list);
        rolePermissionRepository.deleteByPermissionIdIn(Arrays.asList(ids));
        if (deleteLevelThree) {
            adminAuthentication.init();
        }
    }

    @Transactional
    public void updatePermission(Permission entity) {
        if (ParamUtil.isBlank(entity.getId())) {
            throw new BaseException(Resp.ResStatus.PARAM_ERROR, "id不能为空");
        }
        Permission e = findOne(entity.getId());
        if (e == null) {
            throw new BaseException(Resp.ResStatus.PARAM_ERROR, "该权限不存在");
        }
        boolean pathUpdate = false;
        if (!e.getPath().equals(entity.getPath())) {
            pathUpdate = true;
        }
        //获取Hutool拷贝实例
        CopyOptions copyOptions = CopyOptions.create();
        //忽略为null值得属性
        copyOptions.setIgnoreNullValue(true);
        //进行属性拷贝
        BeanUtil.copyProperties(entity, e, copyOptions);
        //对实体类中的@validation注解进行校验
        BindingResult bindingResult = Validation.valid(e);
        if (!bindingResult.isFlag()) {
            throw new BaseException(Resp.ResStatus.PARAM_ERROR, bindingResult.getMessage().get(0));
        }
        update(e);
        if (pathUpdate) {
            adminAuthentication.init();
        }
    }

    public List<PermissionVO> findMenuList(String userId) {
        User user = userRepository.findOne(userId);
        List<RolePermission> rolePermissions = rolePermissionRepository.findByRoleId(user.getRoleId());
        //获取这些角色的所有权限
        Set<String> permissionIds = rolePermissions.parallelStream()
                .map(RolePermission::getPermissionId)
                .collect(Collectors.toSet());
        List<Permission> permissions = permissionRepository.findByLevelNotAndIdIn(3, permissionIds);
        Map<String, List<Permission>> levelTwo = permissions.parallelStream()
                .filter(permission -> permission.getLevel() == 2)
                .sorted(Comparator.comparing(Permission::getSortOrder))
                .collect(Collectors.groupingBy(Permission::getParentId, LinkedHashMap::new, Collectors.toList()));
        Map<String, Permission> levelOne = permissions.parallelStream()
                .filter(permission -> permission.getLevel() == 1)
                .sorted(Comparator.comparing(Permission::getSortOrder))
                .collect(Collectors.toMap(Permission::getId, p -> p, (p1, p2) -> p2, LinkedHashMap::new));
        List<PermissionVO> permissionVOList = new ArrayList<>(levelOne.size());
        levelOne.forEach((id, p) -> {
            PermissionVO permissionVO = new PermissionVO();
            BeanUtil.copyProperties(p, permissionVO);
            List<Permission> children = levelTwo.get(id);
            List<PermissionVO> childrenVOList = new ArrayList<>(children.size());
            for (Permission child : children) {
                PermissionVO vo = new PermissionVO();
                BeanUtil.copyProperties(child, vo);
                childrenVOList.add(vo);
            }
            permissionVO.setChildrenVO(childrenVOList);
            permissionVOList.add(permissionVO);
        });
        return permissionVOList;
    }

    public List<Permission> findAllList() {
        List<Permission> permissions = permissionRepository.findByLevelOrderBySortOrder(1);
        for (Permission p1 : permissions) {
            List<Permission> children1 = permissionRepository.findByParentIdOrderBySortOrder(p1.getId());
            p1.setChildren(children1);
            for (Permission p2 : children1) {
                List<Permission> children2 = permissionRepository.findByParentIdOrderBySortOrder(p2.getId());
                p2.setChildren(children2);
            }
        }
        return permissions;
    }
}
